<?php

namespace app\common\validate;

use think\Validate;

class Base extends Validate
{

    public static function factory() {
        return new static();
    }

    /**
     * 验证规则
     */
    protected $rule = [
    ];
    /**
     * 提示消息
     */
    protected $message = [
    ];
    /**
     * 验证场景
     */
    protected $scene = [
        'add'  => [],
        'edit' => [],
    ];

    public function isScene($scene)
    {
        return array_key_exists($scene, $this->scene);
    }

    //重构验空函数
    protected function require($value, $rule, $data = []) {
        if (method_exists($this, $rule)) {
            if($this->$rule($value, $rule, $data)) {
                return true;
            }
        }
        $result = empty($value) && $value !== 0 && $value !== '0';
        if(!$result) {
            return true;
        }
        if($rule) {
            return $data[$rule];
        } else {
            return false;
        }
    }

    //验证是否有管理员操作权限
    protected function hasAdminOperation($value, $rule, $data = []) {
        return true;
    }

    //判断数据是否存在
    protected function has($value, $rule, $data = []) {
        $rule = explode(',', $rule);
        $modelName = $rule[0];
        $key = 'id';
        if(count($rule) > 1) {
            $key = $rule[1];
        }
        $count = loadModel($modelName)->where([$key => $value])->count();
        return $count > 0;
    }

    //验证信息是否是当前用户的
    protected function isUser($value, $rule, $data = []) {
        $rule = explode(',', $rule);
        $modelName = $rule[0];
        $upk = 'uid';
        if(count($rule) > 1) {
            $upk = $rule[1];
        }
        $pk = 'id';
        if(count($rule) > 2) {
            $pk = $rule[2];
        }
        $row = loadOnly('Model')->find($modelName, $value);
        return $row && isset($data[$upk]) && $row[$upk] == $data[$upk];
    }

    //批量验证信息是否是当前用户的
    protected function isUsers($value, $rule, $data = [], $name = '') {
        $rule = explode(',', $rule);
        $modelName = $rule[0];
        $upk = 'uid';
        if(count($rule) > 1) {
            $upk = $rule[1];
        }
        $pk = 'id';
        if(count($rule) > 2) {
            $pk = $rule[2];
        }
        $model = loadModel($modelName);
        
        $data = $model->whereIn($pk, $value)->where($upk, '<>', $data[$upk])->field('id')->find();
        if($data) {
            $key = $name . '.' . 'isUsers';
            $message = isset($this->message['$key']) ? $this->message['$key'] : '不属于您';
            return $data['id'] . $message;
        }
        return true;
    }

    //验证修改的信息是否属于主模型
    protected function isOwner($value, $rule, $data = []) {
        $rule = explode(',', $rule);
        $modelName = $rule[0];
        $upk = 'sid';
        if(count($rule) > 1) {
            $upk = $rule[1];
        }
        $pk = 'id';
        if(count($rule) > 2) {
            $pk = $rule[2];
        }
        $model = loadModel($modelName);
        $row = $model->where([$pk => $value])->find();
        return $row && isset($data[$upk]) && $row[$upk] == $data[$upk];
    }

    //验证数据是否是显示状态
    protected function isShow($value, $rule, $data = []) {
        $rule = explode(',', $rule);
        $modelName = $rule[0];
        $upk = 'uid';
        if(count($rule) > 1) {
            $upk = $rule[1];
        }
        $pk = 'id';
        if(count($rule) > 2) {
            $pk = $rule[2];
        }
        $model = loadModel($modelName);
        $data = $model->where([$pk => $value])->find();
        if(empty($data )) {
            return false;
        }
        return $data->getIsShowAttr();
    }

    //验证薪资待遇是否合法
    protected function checkSalary($value, $rule, $data = []) {
        if($value == '面议') {
            return true;
        }
        if(preg_match("/^[1-9]\d*$/", $value)) {
            return true;
        }
        $arr = explode('-', $value);
        if(count($arr) != 2) {
            return '不合法';
        }
        if(!preg_match("/^[1-9]\d*$/", $arr[0]) || !preg_match("/^[1-9]\d*$/", $arr[1])) {
            return '不合法';
        }
        if(intval($arr[1]) <= intval($arr[0])) {
            return '不合法';
        }
        return true;
    }

    //验证标签集是否合法
    protected function checkLabels($value, $rule = 10, $data = []) {
        $arr = explode(',', $value);
        if(!$rule) {
            $rule = 10;
        }
        foreach ($arr as $key => $value) {
            if(strlen($value) > $rule) {
                return '标签长度不能大于10';
                break;
            }
        }
        return true;
    }

    //数据库里最多存在的数量，比如单用户不能创建多余该数的数据o
    protected function count($value, $rule, $data = [], $name) {
        $rule = explode(',', $rule);
        $table = $rule[0];
        $count = isset($rule[1]) ? $rule[1] : 1;
        $dcount = Db::name($table)->where([$name => $value])->count();
        return $dcount < $count;
    }

    //验证是否是手机号
    protected function isMobile($value, $rule, $data = [], $name) {
        $reg = '/^1[3456789]\d{9}$/';
        return preg_match($reg, $value) ? true : false;
    }

    //是否是枚举里的值
    protected function isOptions($value, $rule, $data = [], $name = '') {
        $rule = explode(',', $rule);
        $modelName = $rule[0];
        $funName = 'get_options';
        if(count($rule) > 1) {
            $funName = $rule[1];
        }
        $model = loadEnum($modelName);
        $options = $model->$funName();
        return isset($options[$value]);
    }

    //是否有指定的数据
    protected function hasOne($value, $rule, $data = [], $name) {
        $rule = explode(',', $rule);
        $modelName = $rule[0];
        $pk = 'id';
        $length = count($rule);
        if($length > 1) {
            $pk = $rule[1];
        }
        $model = loadModel($modelName);
        $where = [$pk => $value];
        if($length > 2) {
            for($i = 2; $i < $length; $i++) {
                $where[$arr[$i]] = $data[$arr[$i]];
            }
        }
        $data = $model->where($where)->find();
        return !empty($data);
    }

    //验证年月时间段是否合法
    protected function timeslot($value, $rule, $data = []) {
        if(DateTime::createFromFormat('Y-m', $value)->format('Y-m') != $value) {
            return false;
        }
        if(DateTime::createFromFormat('Y-m', $data[$rule])->format('Y-m') != $data[$rule]) {
            return false;
        }
        if(strtotime($value, "-01") >= strtotime($data[$rule], "-01")) {
            return false;
        }
        return true;
    }

    //验证主键搜索到的数据中的外键是否和验证数据里的一致
    protected function isBelongTo($value, $rule, $data = [], $name) {
        $rule = explode(',', $rule);
        $modelName = $rule[0];
        $pk = 'id';
        $length = count($rule);
        if($length > 1) {
            $pk = $rule[1];
        }
        if(!isset($data[$pk]) || !$data[$pk]) {
            return true;
        }
        $model = loadModel($modelName);
        $where = [$pk => $data[$pk]];
        $data = $model->where($where)->find();
        return $data[$name] == $value;
    }

    protected function isValidCardNumber($cardNumber, $rule, $data = [])
    {
        // 移除所有空格和破折号
        $cardNumber = str_replace([' ', '-'], '', $cardNumber);
 
        // 检查卡号长度（一般为16或19位）
        if (!ctype_digit($cardNumber) || (strlen($cardNumber) != 16 && strlen($cardNumber) != 19 && strlen($cardNumber) != 20)) {
            return false;
        }
 
        // 使用Luhn算法验证卡号
        return true;//$this->luhnCheck($cardNumber, $rule, $data);
    }
 
    /**
     * Luhn算法校验银行卡号
     * @param string $cardNumber 银行卡号
     * @return bool
     */
    protected function luhnCheck($cardNumber, $rule, $data = [])
    {
        $numSum = 0;
        $numDigits = strlen($cardNumber);
        $parity = $numDigits % 2;
 
        for ($i = 0; $i < $numDigits; $i++) {
            $digit = $cardNumber[$i];
            if ($i % 2 == $parity) {
                $digit *= 2;
                if ($digit > 9) {
                    $digit -= 9;
                }
            }
            $numSum += $digit;
        }
        return ($numSum % 10 == 0);
    }

    // 检测身份证合法
    protected function idCard($value, $rule, $data = [])
    {
        return !!preg_match('/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/', $value);
    }

    //验证日期格式是否合法
    protected function date($value, $rule = '', $data = [], $field = '')
    {
        // 验证 $value 是否为有效的日期格式
        if (strtotime($value) === false) {
            return '日期格式不正确';
        }
        return true;
    }

    // 效验开始日期是否大于结束日期
    protected function checkEndDate($value, $rule, $data = []) {
        $start_date = strtotime($data[$rule]);
        $end_date = strtotime($value);
        return $end_date > $start_date;
    }

    // 锁死不能使用该变量，比如禁止编辑和删除
    protected function lock($value, $rule, $data = []) {
        return !$value;
    }

    // 自定义验证重复，可以验证多字段是否同时相同
    protected function xunique($value, $rule, $data = [], $name) {
        $rule = explode(',', $rule);
        $model = array_shift($rule);
        $model = loadModel($model);
        $pk = array_shift($rule);
        if(!$pk) {
            $pk = 'id';
        }
        $model->where($name, $value);
        if(isset($data[$pk])) {
            $model->where($pk, '<>', $data[$pk]);
        }
        foreach ($rule as $k => $v) {
            $model->where($v, $data[$v]);
        }
        $count = $model->count();
        return !$count;
    }   
}
